#include "Avalon/Base/Base.hpp"
#include <cmath>
#include <boost/thread.hpp>
#ifdef WIN32
  #include <windows.h>
#endif

using namespace Avalon;
using namespace boost;
using namespace std;

namespace {
  double RoundDouble(double value) {
    if(value >= 0) {
      return floor(value + 0.5);
    } else {
      return ceil(value + 0.5);
    }
  }

  bool running = true;
  mutex runMutex;

#ifdef WIN32
  BOOL CtrlHandler(DWORD ctrl) {
    switch(ctrl) {
      case CTRL_C_EVENT:
        {
          lock_guard<mutex> lock(runMutex);
          running = false;
        }
        return true;
    }
    return false;
  }

  bool IsRunning() {
    static BOOL initializeControlHandler = SetConsoleCtrlHandler(
      reinterpret_cast<PHANDLER_ROUTINE>(CtrlHandler), TRUE);
    lock_guard<mutex> lock(runMutex);
    return running;
  }
#else
  bool IsRunning() {
    return true;
  }
#endif
}

bool Avalon::IsBigEndian() {
  static const int i = 1;
  return *reinterpret_cast<const char*>(&i) != 1;
}

double Avalon::Ceil(double value, double point) {
  double d = value / point;
  d = ceil(d);
  return d * point;
}

int Avalon::Ceil(int value, int point) {
  double d = static_cast<double>(value) / point;
  d = ceil(d) + 0.5;
  return static_cast<int>(d) * point;
}

double Avalon::Floor(double value, double point) {
  double d = value / point;
  d = floor(d);
  return d * point;
}

int Avalon::Floor(int value, int point) {
  double d = static_cast<double>(value) / point;
  d = floor(d) + 0.5;
  return static_cast<int>(d) * point;
}

double Avalon::Round(double value, double point) {
  double d = value / point;
  d = RoundDouble(d);
  return d * point;
}

int Avalon::Round(int value, int point) {
  double d = static_cast<double>(value) / point;
  d = RoundDouble(d) + 0.5;
  return static_cast<int>(d) * point;
}

bool Avalon::ReceivedKillEvent() {
  return !IsRunning();
}
